#ifndef RSIM_QUATERNION_H
#define RSIM_QUATERNION_H

/* -------------------------------------------------------------------------- *
* File: Quaternion.h                                                         *
* Authors: Kishor Bhalerao                                                   *
* Email : kishor8dm@gmail.com                                                *
* Contributors:                                                              *
* Email:                                                                     *
* copyright (c) 2010 Authors.                                                *
*                                                                            *
* This program is free software: you can redistribute it and/or modify it    *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or any later version.*
*                                                                            *
* This program is distributed in the hope that it will be useful, but        *
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
* or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   *
* for more details. (http://www.gnu.org/licenses/)                           *
* -------------------------------------------------------------------------- */


#include "Vect4.h"
#include "LinAlgDecl.h"

namespace RSIM{

class Rotation;
        
/** 	Quaternion is a 4x1 vector [e0 e1 e2 e3] with e0 being the scalar.
        Thus if rotation about quaternion vector v is theta, then the 
        quaternions are given by 
        e0 = cos(theta/2)
        [e1 e2 e3] = v*sin(theta/2)
*/
class Quaternion:public Vect4_<double>{
        public:
                /** Default constructor sets the quaternion to zero rotation */
                Quaternion();
                
                /** set quaternion from vect4 */
                explicit Quaternion(const Vect4& q);
                
                /** set quaternion from double */
                Quaternion(const double& e0, const double& e1, 
                        const double& e2, const double& e3);
                                        
                /** set quaternion from rotation matrix. No checks to ensure 
                that Rot is a valid Rotation matrix. */
                explicit Quaternion(const Rotation& Rot);
                
                
                static void calcQuaternionFromEulerAngles(      const double& ang1,
                                                                const double& ang2,
                                                                const double& ang3,
                                                                const char *ptr,
                                                                double *Quat);
                
                /** Normalize the quaternion. This is needed to get rid
                of the drift introduced in the simulation on numerical
                integration. */
                void normalize();
};

} // namespace RSIM

#endif